package edu.cmu.cs.stage3.alice.core.property;

import java.io.IOException;

import edu.cmu.cs.stage3.alice.core.Element;
import edu.cmu.cs.stage3.alice.core.ReferenceGenerator;
import edu.cmu.cs.stage3.alice.core.applet.AppletXmlStruct;
import edu.cmu.cs.stage3.io.DirectoryTreeStorer;

public class DictionaryProperty extends ObjectProperty {

 // The separator mark for tags in HTML - complementary with 'MARK' for XML
 // - see 'edu.cmu.cs.stage3.alice.authoringtool.AuthoringTool.viewHtml()'; 'edu.cmu.cs.stage3.alice.core.AppletWorldStorer.internalStore(Element,final int,ReferenceGenerator)'
 private static final char MARK = edu.cmu.cs.stage3.alice.core.AppletWorldStorer.MARK;

 public DictionaryProperty (Element owner, String name, java.util.Dictionary defaultValue) {
  super( owner, name, defaultValue, java.util.Dictionary.class );
  }

 public java.util.Dictionary getDictionaryValue () {
  return (java.util.Dictionary)getValue();
  }

 //Rem @Override
 protected void decodeObject (org.w3c.dom.Element node, java.util.Vector referencesToBeResolved) throws java.io.IOException {
  java.util.Dictionary dict = new java.util.Hashtable();
  org.w3c.dom.NodeList entryNodeList = node.getElementsByTagName( "entry" );
  for (int i=0; i<entryNodeList.getLength(); i++) {
   org.w3c.dom.Element entryNode = (org.w3c.dom.Element)entryNodeList.item( i );
   org.w3c.dom.Element keyNode = (org.w3c.dom.Element)entryNode.getElementsByTagName( "key" ).item( 0 );
   String keyTypeName = keyNode.getAttribute( "class" );
   Object key;
   try {
    Class keyType = Class.forName( keyTypeName );
    if (keyType == String.class) {
     key = getNodeText( keyNode );
    } else {
     key = getValueOf( keyType, getNodeText( keyNode ) );
     }
   } catch( ClassNotFoundException cnfe) {
    throw new RuntimeException( keyTypeName );
    }

   org.w3c.dom.Element valueNode = (org.w3c.dom.Element)entryNode.getElementsByTagName( "value" ).item( 0 );
   String valueTypeName = valueNode.getAttribute( "class" );
   Object value;
   try {
    Class valueType = Class.forName( valueTypeName );
    if (valueType == String.class) {
     value = getNodeText( valueNode );
    } else {
     value = getValueOf( valueType, getNodeText( valueNode ) );
     }
   } catch( ClassNotFoundException cnfe) {
    throw new RuntimeException( valueTypeName );
    }
   dict.put( key, value );
   }
  set( dict );
  }

 //Rem @Override
 protected void encodeObject (org.w3c.dom.Document document, org.w3c.dom.Element node, DirectoryTreeStorer storer, edu.cmu.cs.stage3.alice.core.ReferenceGenerator referenceGenerator) throws java.io.IOException {
  java.util.Dictionary dict = getDictionaryValue();
  if (dict!=null) {
   java.util.Enumeration enu = dict.keys();
   while (enu.hasMoreElements()) {
    Object key = enu.nextElement();
    Object value = dict.get( key );

    org.w3c.dom.Element entryNode = document.createElement( "entry" );

    org.w3c.dom.Element keyNode = document.createElement( "key" );
    keyNode.setAttribute( "class", key.getClass().getName() );
    keyNode.appendChild( createNodeForString( document, key.toString() ) );

    org.w3c.dom.Element valueNode = document.createElement( "value" );
    valueNode.setAttribute( "class", value.getClass().getName() );
    valueNode.appendChild( createNodeForString( document, value.toString() ) );

    entryNode.appendChild( keyNode );
    entryNode.appendChild( valueNode );
    node.appendChild( entryNode );
    }
   }
  }

 //Rem @Override
 protected AppletXmlStruct encodeObjectToXml (ReferenceGenerator referenceGenerator) throws IOException {
  java.util.Dictionary dict = getDictionaryValue();
  AppletXmlStruct struct = new AppletXmlStruct();
  if (dict!=null) {
   java.util.Enumeration enu = dict.keys();
   while (enu.hasMoreElements()) {
    Object key = enu.nextElement();
    Object value = dict.get( key );
    struct.addElement("<entry>");

    struct.addElement("<key class=" + MARK + key.getClass().getName() + MARK + ">");
    struct.addElement(key.toString());
    struct.addElement("</key>");

    struct.addElement("<value class=" + MARK + value.getClass().getName() + MARK + ">");
    struct.addElement(value.toString());
    struct.addElement("</value>");

    struct.addElement("</entry>");
    }
   }
  return struct;
  }

 public Object get (Object key) {
  java.util.Dictionary dict = getDictionaryValue();
  if (dict!=null) {
   return dict.get( key );
  } else {
   return null;
   }
  }

 public boolean isEmpty () {
  java.util.Dictionary dict = getDictionaryValue();
  if (dict!=null) {
   return dict.isEmpty();
  } else {
   return true;
   }
  }

 public Object put (Object key, Object value) {
  java.util.Dictionary dict = getDictionaryValue();
  java.util.Dictionary newDict = new java.util.Hashtable();
  if (dict!=null) {
   //todo: optimize?
   java.util.Enumeration enu = dict.keys();
   while (enu.hasMoreElements()) {
    Object k = enu.nextElement();
    Object v = dict.get( k );
    newDict.put( k, v );
    }
   }
  Object o = newDict.put( key, value );
  set( newDict );
  return o;
  }

 public Object remove (Object key) {
  java.util.Dictionary dict = getDictionaryValue();
  java.util.Dictionary newDict = new java.util.Hashtable();
  Object value = null;
  if (dict!=null) {
   //todo: optimize?
   java.util.Enumeration enu = dict.keys();
   while (enu.hasMoreElements()) {
    Object k = enu.nextElement();
    Object v = dict.get( k );
    if (k.equals( key )) {
     value = v;
    } else {
     newDict.put( k, v );
     }
    }
   }
  if (value!=null) {
   set( newDict );
   }
  return value;
  }

 }
